package org.jeecg.report.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.qis.entity.QisSpcdetailCfg;
import org.jeecg.qis.service.IQisSpcdetailCfgService;
import org.jeecg.qis.service.IQisSpcheadCfgService;
import org.jeecg.report.dto.QisSpcChartDataDTO;
import org.jeecg.report.entity.QisSpcGroupData;
import org.jeecg.report.entity.QisSpcPointValue;
import org.jeecg.report.mapper.QisSpcMapper;
import org.jeecg.report.service.IQisSpcService;
import org.jeecg.report.utils.QisSpcUtil;
import org.jeecg.report.vo.QisSpcParameterVO;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class IQisSpcServiceImpl implements IQisSpcService {

    private IQisSpcheadCfgService iQisSpcheadCfgService;
    @Autowired
    private IQisSpcdetailCfgService iQisSpcdetailCfgService;
    @Autowired
    private QisSpcMapper qisSpcMapper;
    @Override
    public Result<QisSpcChartDataDTO> getChartInfo(QisSpcParameterVO qisSpcParameterVO) {
        //整合查询条件数据

        QisSpcParameterVO parameter =qisSpcMapper.SupplementarySpcParameter(qisSpcParameterVO);
        if(Objects.nonNull(qisSpcParameterVO.getWoId())){
            parameter.setWoId(qisSpcParameterVO.getWoId());
        }
        if(Objects.nonNull(qisSpcParameterVO.getSDate())){
            parameter.setSDate(qisSpcParameterVO.getSDate());
        }
        if(Objects.nonNull(qisSpcParameterVO.getEDate())){
            parameter.setEDate(qisSpcParameterVO.getEDate());
        }
        if(Objects.nonNull(qisSpcParameterVO.getUnitsn())){
            parameter.setUnitsn(qisSpcParameterVO.getUnitsn());
        }
        //根据所有的配置与规格限，查找源数据
        List<QisSpcPointValue> list = getSpcData(parameter);
        if (list.isEmpty()) {
            return Result.error(500, "无数据");
        }
        Integer spcTyp = parameter.getSpcTyp();
        //2.判断是均值极差还是单值极差
        if (Objects.nonNull(spcTyp) && spcTyp>1) {
            //均值极差图
            QisSpcChartDataDTO xRListByParam = getXRListByParam(parameter, list);
            return Result.OK(xRListByParam);
        } else {
            QisSpcChartDataDTO xmrListByParam = getXMRListByParam(parameter, list);
            return Result.OK(xmrListByParam);
        }
        //3.统计直方图数据

        //4.将算完的数据再进行一遍异常判断

    }

    private void getCpkInfo(List<QisSpcPointValue> list,QisSpcChartDataDTO qisSpcChartDataDTO){
        log.info("开始计算直方图数据");
        //平均值
        BigDecimal avg = QisSpcUtil.avg(list);
        //最大值
        qisSpcChartDataDTO.setMaxiMum(QisSpcUtil.getMax(list));
        //最小值
        qisSpcChartDataDTO.setMiniMum(QisSpcUtil.getMin(list));
        //中位数
        qisSpcChartDataDTO.setMedian(QisSpcUtil.getMedian(list));
        //西格玛（组内）
        BigDecimal sigma = QisSpcUtil.getSigma(qisSpcChartDataDTO.getClR(), qisSpcChartDataDTO.getN());
        qisSpcChartDataDTO.setSigma(sigma);
        //西格玛（总）
        BigDecimal sigmaP = QisSpcUtil.getSigmaP(list, avg, list.size());
        qisSpcChartDataDTO.setSigmaP(sigmaP.setScale(6, RoundingMode.HALF_UP));
        //cpu
        if (Objects.nonNull(qisSpcChartDataDTO.getUsl())){
            BigDecimal cpu = QisSpcUtil.getCpuORPpu(qisSpcChartDataDTO.getUsl(), avg, sigma);
            BigDecimal ppu = QisSpcUtil.getCpuORPpu(qisSpcChartDataDTO.getUsl(), avg, sigmaP);
            qisSpcChartDataDTO.setCpu(cpu);
            qisSpcChartDataDTO.setCpk(cpu);
            qisSpcChartDataDTO.setPpu(ppu);
            qisSpcChartDataDTO.setPpk(ppu);
        }
        //cpl
        if (Objects.nonNull(qisSpcChartDataDTO.getLsl())){
            BigDecimal cpl = QisSpcUtil.getCplORPpl(qisSpcChartDataDTO.getLsl(), avg, sigma);
            BigDecimal ppl = QisSpcUtil.getCplORPpl(qisSpcChartDataDTO.getLsl(), avg, sigmaP);
            qisSpcChartDataDTO.setCpl(cpl);
            qisSpcChartDataDTO.setCpk(cpl);
            qisSpcChartDataDTO.setPpl(ppl);
            qisSpcChartDataDTO.setPpk(ppl);
        }
        //cp
        if (Objects.nonNull(qisSpcChartDataDTO.getLsl()) && Objects.nonNull(qisSpcChartDataDTO.getUsl())){
            BigDecimal cp = QisSpcUtil.getCpORPp(qisSpcChartDataDTO.getUsl(), qisSpcChartDataDTO.getLsl(),sigma);
            BigDecimal pp = QisSpcUtil.getCpORPp(qisSpcChartDataDTO.getUsl(), qisSpcChartDataDTO.getLsl(), sigmaP);
            qisSpcChartDataDTO.setCp(cp);
            qisSpcChartDataDTO.setCpk(qisSpcChartDataDTO.getCpu().min(qisSpcChartDataDTO.getCpl()));
            qisSpcChartDataDTO.setPp(pp);
            qisSpcChartDataDTO.setPpk(qisSpcChartDataDTO.getPpu().min(qisSpcChartDataDTO.getPpl()));
        }
    }



    private QisSpcChartDataDTO getXMRListByParam(QisSpcParameterVO qisSpcParameterVO, List<QisSpcPointValue> list) {
        QisSpcChartDataDTO qisSpcChartDataDTO = new QisSpcChartDataDTO();
        if (list.size() < 1) {
            return qisSpcChartDataDTO;
        }
        //新增逻辑 过滤超过规格线的异常数据用于计算正常的控制线
        List<QisSpcPointValue> normalList = new ArrayList<>(list);
        if(Objects.nonNull(qisSpcParameterVO.getUsl())){
            normalList = normalList.stream().filter(item -> item.getValue().compareTo(qisSpcParameterVO.getUsl()) <= 0).collect(Collectors.toList());
        }
        if(Objects.nonNull(qisSpcParameterVO.getLsl())){
            normalList = normalList.stream().filter(item -> item.getValue().compareTo(qisSpcParameterVO.getLsl()) >= 0).collect(Collectors.toList());
        }
        //List<QisSpcPointValue> normalList = list.stream().filter(item -> item.getValue().compareTo(qisSpcParameterVO.getUsl()) <= 0 && item.getValue().compareTo(qisSpcParameterVO.getLsl()) >= 0 ).collect(Collectors.toList());
        if (normalList.size() < 1) {
            return qisSpcChartDataDTO;
        }
        List<QisSpcPointValue> normalrangeList = getRangeList(normalList,qisSpcChartDataDTO,false);
        if ("1".equals(qisSpcParameterVO.getStage())) {
            setControlValue(qisSpcParameterVO, qisSpcChartDataDTO);
        } else {
            QisSpcUtil.singleValueControlLimit(qisSpcChartDataDTO,normalList,normalrangeList);
        }
        qisSpcChartDataDTO.setN(1);
        qisSpcChartDataDTO.setCount(normalList.size());
        qisSpcChartDataDTO.setSubGroup(normalList.size());
        qisSpcChartDataDTO.setUsl(qisSpcParameterVO.getUsl());
        qisSpcChartDataDTO.setLsl(qisSpcParameterVO.getLsl());
        //获取异常规则
        List<QisSpcdetailCfg> spcdetailCfgList = iQisSpcdetailCfgService.list(new LambdaQueryWrapper<QisSpcdetailCfg>()
                .eq(QisSpcdetailCfg::getHeadid, qisSpcParameterVO.getRecId()));
        List<QisSpcPointValue> rangeList = getRangeList(list,qisSpcChartDataDTO,true);
        //计算直方图数据
        getCpkInfo(normalList,qisSpcChartDataDTO);
        spcdetailCfgList.forEach(item->{
            switch (item.getDictid()){
                case "R0":
                    QisSpcUtil.getAbnormal0(list,item,qisSpcChartDataDTO);
                    break;
                case "R1":
                    QisSpcUtil.getAbnormal1(list,item,qisSpcChartDataDTO);
                    break;
                case "2":
                    QisSpcUtil.getAbnormal2(list,item,qisSpcChartDataDTO);
                    break;
                case "R3":
                    break;
                case "R4":
                    break;
                case "R5":
                    break;
                case "R6":
                    break;
                case "R7":
                    break;

            }
        });
        qisSpcChartDataDTO.setControlValues(list);
        qisSpcChartDataDTO.setRangeValues(rangeList);
        //八项判异规则
        return qisSpcChartDataDTO;
    }

    private List<QisSpcPointValue> getRangeList(List<QisSpcPointValue> list,QisSpcChartDataDTO qisSpcChartDataDTO, boolean flag){
        BigDecimal lsl = qisSpcChartDataDTO.getLsl();
        BigDecimal usl = qisSpcChartDataDTO.getUsl();
        BigDecimal uclX = qisSpcChartDataDTO.getUclX();
        BigDecimal uclR = qisSpcChartDataDTO.getUclR();
        BigDecimal lclX = qisSpcChartDataDTO.getLclX();
        List<QisSpcPointValue> rangeList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if (i != 0) {
                BigDecimal value = list.get(i).getValue();
                QisSpcPointValue pointValue = new QisSpcPointValue();
                BigDecimal XX = list.get(i - 1).getValue();
                BigDecimal subtract = value.subtract(XX).setScale(4, BigDecimal.ROUND_HALF_UP).abs();;
                pointValue.setValue(subtract);
                if (flag){
                    if (subtract.compareTo(uclR)>0){
                        pointValue.setColor("yellow");
                    }else {
                        pointValue.setColor("green");
                    }
                    if (Objects.nonNull(usl)&&value.compareTo(usl) > 0){
                        list.get(i).setColor("red");
                    }else if(Objects.nonNull(lsl)&&value.compareTo(lsl)<0){
                        list.get(i).setColor("red");
                    } else if (value.compareTo(uclX) > 0|| value.compareTo(lclX)<0){
                        list.get(i).setColor("yellow");
                    }else {
                        list.get(i).setColor("green");
                    }
                }
                pointValue.setName(list.get(i).getName());
                pointValue.setId(list.get(i).getId()+"-"+list.get(i-1).getId());
                rangeList.add(pointValue);
            }
        }
        return rangeList;
    }

    private QisSpcChartDataDTO getXRListByParam(QisSpcParameterVO qisSpcParameterVO, List<QisSpcPointValue> list) {
        return null;
    }
    private void setControlValue(QisSpcParameterVO qisSpcParameterVO, QisSpcChartDataDTO qisSpcChartDataDTO) {
    }

    private List<QisSpcPointValue>  getSpcData(QisSpcParameterVO qisSpcParameterVO){
        return qisSpcMapper.getSpcPointValueListByParam(qisSpcParameterVO);
    }


    @Override
    public ModelAndView exportXls(HttpServletRequest request, QisSpcParameterVO qisSpcParameterVO) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<QisSpcPointValue> list = getSpcData(qisSpcParameterVO);
        List<QisSpcPointValue> normalList = new ArrayList<>(list);
        String title = "质控点源数据";
        // Step.3 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        //此处设置的filename无效 ,前端会重更新设置一下
        mv.addObject(NormalExcelConstants.FILE_NAME, title);
        mv.addObject(NormalExcelConstants.CLASS, QisSpcPointValue.class);
        //update-begin--Author:liusq  Date:20210126 for：图片导出报错，ImageBasePath未设置--------------------
        ExportParams exportParams = new ExportParams("检验项目:" + qisSpcParameterVO.getDescription(), "导出人:" + sysUser.getRealname(), title);
        //update-end--Author:liusq  Date:20210126 for：图片导出报错，ImageBasePath未设置----------------------
        mv.addObject(NormalExcelConstants.PARAMS, exportParams);
        mv.addObject(NormalExcelConstants.DATA_LIST, list);
        return mv;
    }

    @Override
    public Result<QisSpcChartDataDTO> getManualChartInfo(QisSpcParameterVO qisSpcParameterVO) {
        //根据工单号拿到要做SPC的点位
        QisSpcParameterVO qisSpcParameterByWoID = qisSpcMapper.getQisSpcParameterByWoID(qisSpcParameterVO);
        qisSpcParameterByWoID.setSpcTyp(1);
        //qisSpcParameterByWoID.setOp("OP90");
        if (Objects.nonNull(qisSpcParameterByWoID)){
            return getChartInfo(qisSpcParameterByWoID);
        }else {
            return Result.OK("");
        }
    }

    @Override
    public Result<QisSpcChartDataDTO> getSampleChartInfo(QisSpcParameterVO qisSpcParameterVO) {
        QisSpcChartDataDTO qisSpcChartDataDTO = new QisSpcChartDataDTO();
        //查一个RecID

        //根据样本号进行分组计算 计算组均值与组极差
        List<QisSpcPointValue> spcData = getSpcData(qisSpcParameterVO);
        if (spcData.isEmpty()){
            return Result.OK(qisSpcChartDataDTO);
        }
        List<QisSpcPointValue> rangeList = getRangeList(spcData, qisSpcChartDataDTO, false);
        //计算控制线
        QisSpcUtil.singleValueControlLimit(qisSpcChartDataDTO,spcData,rangeList);
        qisSpcChartDataDTO.setControlValues(spcData);
        qisSpcChartDataDTO.setRangeValues(rangeList);
        return Result.OK(qisSpcChartDataDTO);
    }

    private List<QisSpcGroupData>  getSampleSpcData(QisSpcParameterVO qisSpcParameterVO){
        return qisSpcMapper.getSampleSpcDataByParam(qisSpcParameterVO);
    }
}
